/*
========================================================================
 Name        : SingaporeBusDocument.cpp
 Author      : 
 Copyright   : Your copyright notice
 Description : 
========================================================================
*/
// [[[ begin generated region: do not modify [Generated User Includes]
#include "SingaporeBusDocument.h"
#include "SingaporeBusAppUi.h"
// ]]] end generated region [Generated User Includes]

#include <AknsFrameBackgroundControlContext.h>
#include <aknmessagequerydialog.h>
#include <http.h>
#include "SingaporeBus.hrh"
#include "PublicTransportMapContainerView.h"
#include "CSingaporeBusServicesView.h"
#include "CSingaporeBusStopsView.h"
#include "CSingaporeBusServicesArrivalTimeView.h"
#include "CSingaporeBusRouteView.h"
#include "CSingaporeBusServiceRouteView.h"
#include "CSingaporeBusFavoritesView.h"
#include <aknglobalnote.h> 
#include <aknnotewrappers.h> 
#include <S32FILE.H>
#include <eikapp.h>
#include "LbsCommon.h"
#include "BAUTILS.h"
#include <SingaporeBus.rsg>
#include "CharUtils.h"
#include <aknglobalconfirmationquery.h>
#include <hal.h>
#include "Function.h"
#include "Binder.h"
#include "MathUtils.h"
#include "PublicTransportTileRequest.h"
#include "SingaporeBus_aif.mbg"
const TInt DndTimedOut = -5120;

TUint32 TBuf8Hash(const TBuf8<15>& aPtr)
 {
 return DefaultHash::Des8 (aPtr);
 }

 TBool TBuf8Ident(const TBuf8<15>& aL, const TBuf8<15>& aR)
 {
 return DefaultIdentity::Des8 (aL, aR);
 }


static void PrintNoteL(TRefByValue<const TDesC> aFormat, ...)
    {
    VA_LIST list;
    VA_START(list, aFormat);
    TBuf<256> buf;
    buf.FormatList(aFormat, list);
    VA_END(list);
	CAknGlobalNote* globalNote = CAknGlobalNote::NewLC();
	globalNote->ShowNoteL(EAknGlobalInformationNote, buf); 
    CleanupStack::PopAndDestroy(globalNote);
    }

/**
 * @brief Constructs the document class for the application.
 * @param anApplication the application instance
 */
CSingaporeBusDocument::CSingaporeBusDocument( CEikApplication& anApplication )
	: CAknDocument( anApplication ), iStations(100), iServices(100), iServicesPathsIndex(100), iStationServiceKeys(100), iConnectionActive(EFalse)
	{
		iConnectionManager = NULL;
		iIsConnectionActiveHelper = NULL;
		iSelectedStation = NULL ;
		iOriginStation = NULL ;
		iDestinationStation = NULL ;
		iGooglePositionRequest = NULL;
		iNetworkPositionRequest = NULL;
		iPositionRequest = NULL;
		iScheduleRequestManual = EFalse;
		iCachedTilesCount = 50;
		iAutoCheckForUpdatePeriod = 21;
		iLastAutoCheckForUpdate.HomeTime();
		iCountAutoCheckForUpdateInSession = 0;
		iTimeLastAd.HomeTime();
		iPosition.SetCoordinate(0, 0);
		iGpsGraceTimerHelper = NULL;
		iGpsGraceTime = 0;
		iGpsAvailable = EFalse;
		iGooglePositionRequestWaitingConnection = EFalse;
		iApplicationUpdaterWaitingConnection = EFalse;
		iPendingPositionRequests = 0;
		iServicesStationMap = NULL;
		iJourneyPlannerError = KErrNone;
		iTimeInBackground = Time::MaxTTime();
		iDisplayCalibrationMessage = ETrue;
		iAskUseLocation = ETrue;
		iUseLocation = ETrue;
#ifndef __SERIES60_3X__
		iMagneticNorthDataError = KErrNotFound;
#endif
	}

static void SetHeaderL(RHTTPSession& iSession, RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
  {
	RStringF valStr = iSession.StringPool().OpenFStringL(aHdrValue);
	CleanupClosePushL(valStr);
	THTTPHdrVal val(valStr);
	aHeaders.SetFieldL(iSession.StringPool().StringF(aHdrField,
		RHTTPSession::GetTable()), val);
	CleanupStack::PopAndDestroy();  // valStr
  }


static TInt CleanFavorite(TDes8& aFavorite)
	{
	if(aFavorite[0] == '&')
		{
		TInt sep = aFavorite.Locate(' ');
		TPtrC8 strStation( aFavorite.Mid(1, sep-1) );
		TPtrC8 strServiceKey( aFavorite.Mid(sep+1) );
		if(strStation.Length() == 4)
			aFavorite.Format(_L8("&%S9 %S"), &strStation, &strServiceKey);
		}
	else if(aFavorite[0] == '#')
		{
		
		}
	else
		{
		if(aFavorite.Length() == 4)
			aFavorite.Append('9');
		}
	
	}

TInt CSingaporeBusDocument::LoadSettingsL(TUint& aVersion)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	RFileReadStream reader;
	reader.PushL();   // call CleanupReleasePushL()
	TInt err = reader.Open(iFsData, _L("SingaporeBus.ini"), EFileRead);
	if(err == KErrNone)
		{
		TUint version = reader.ReadUint32L(); // version number
		aVersion = version;
		if(version >= 1)
			{
				iIapPriorityList.Reset();
				TUint count = reader.ReadUint32L();
				for(TUint i = 0 ; i < count ; ++i)
					{
					iIapPriorityList.Append(reader.ReadUint32L());
					}
				{
				TUint count = reader.ReadUint32L();
				for(TUint i = 0 ; i < count ; ++i)
					{
					TBuf8<128> stationNumber;
					reader >> stationNumber;
					
					CleanFavorite(stationNumber);
					
					HBufC8* hStationNumber = stationNumber.AllocLC();
					iStationsLoaded.AppendL(hStationNumber);
					CleanupStack::Pop(hStationNumber);
					iFavoriteStations.AppendL(*hStationNumber);
					iFavorites[0]->InsertL(*hStationNumber);
					}
				iScheduleRequestManual = reader.ReadInt8L();
				}
			}
		if(version >= 2)
			{
			iCachedTilesCount = reader.ReadUint32L();
			}
		if(version >= 3)
			{
			iAutoCheckForUpdatePeriod = reader.ReadInt32L();
			TInt64 timeHi = reader.ReadInt32L();
			TInt64 timeLo = reader.ReadInt32L();
			iLastAutoCheckForUpdate = (timeHi << 32) + timeLo;
			reader >> iInstallationFile;
			}
		if(version >= 4)
			{
			iGpsGraceTime = reader.ReadInt32L();
			}
		if(version >= 5)
			{
			
			TUint favoritesPaneCount = reader.ReadUint32L();
			if(favoritesPaneCount == 0)
				{
				iFavorites[0]->Close();
				delete iFavorites[0];
				iFavorites.Remove(0);
				delete iFavoritesTitles[0];
				iFavoritesTitles.Remove(0);
				}
			for(TUint i = 0 ; i < favoritesPaneCount ; ++i)
				{
				TBuf<128> favoritesTitle;
				reader >> favoritesTitle;
				if(i == 0)
					{
					delete iFavoritesTitles[i];
					iFavoritesTitles[i] = favoritesTitle.AllocL();
					}
				else
					{
					iFavoritesTitles.AppendL( favoritesTitle.AllocL() );
					iFavorites.AppendL( new RHashSet< TBuf8<15> >(&TBuf8Hash, &TBuf8Ident) );
					TUint favoritesCount = reader.ReadUint32L();
					for(TUint j = 0 ; j < favoritesCount ; ++j)
						{
						TBuf8<128> favorite;
						reader >> favorite;
						
						CleanFavorite(favorite);
						
						iFavorites[i]->InsertL(favorite);
						}
					}
				}
			}
		if(version >= 6)
			{
			iDisplayCalibrationMessage = reader.ReadInt32L();
			}
		if(version >= 7)
			{
			iUseLocation = reader.ReadInt32L();
			}
		iAskUseLocation = EFalse; // location use is only asked on first run of the app
		
		if(version == 7 && !iUseLocation)
			{
			iAskUseLocation = ETrue; // to correct a bug in v2.3.1: location disabled when upgrading the app
			}

		}
	CleanupStack::PopAndDestroy(&reader); // release resources 
	return err;
	}


TInt CSingaporeBusDocument::SaveSettingsL()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
		RFileWriteStream writer;
		writer.PushL();   // call CleanupReleasePushL()
		TInt err = writer.Open(iFsData, _L("SingaporeBus.ini"), EFileWrite);
		if (err == KErrNotFound) // file does not exist - create it
			err = writer.Create(iFsData, _L("SingaporeBus.ini"), EFileWrite);
		if(err == KErrNone)
			{
			writer.WriteUint32L(8); // version number
			writer.WriteUint32L(iIapPriorityList.Count());
			for(TUint i = 0 ; i < iIapPriorityList.Count() ; ++i)
				{
				writer.WriteUint32L(iIapPriorityList[i]);
				}
			
			{
			if(iFavorites.Count() > 0)
				{
				writer.WriteUint32L(iFavorites[0]->Count());
				THashSetIter< TBuf8<15> > it (*iFavorites[0]);
				for(it.Next() ; it.Current() ; it.Next())
					{
					writer << *it.Current();
					}
				}
			else
				writer.WriteUint32L(0);
			writer.WriteInt8L(iScheduleRequestManual);	
			writer.WriteUint32L(iCachedTilesCount);	
			writer.WriteInt32L(iAutoCheckForUpdatePeriod);
			writer.WriteInt32L( iLastAutoCheckForUpdate.Int64() >> 32 );
			writer.WriteInt32L( iLastAutoCheckForUpdate.Int64() & 0xFFFFFFFF);
			writer << iInstallationFile;
			
			writer.WriteInt32L(iGpsGraceTime);
			
			
			writer.WriteInt32L(iFavorites.Count());
			for(TInt i = 0 ; i < iFavorites.Count() ; ++i)
				{
				writer << *iFavoritesTitles[i];
				if(i > 0)
					{
					THashSetIter< TBuf8<15> > it (*iFavorites[i]);
					writer.WriteInt32L(iFavorites[i]->Count());
					for(it.Next() ; it.Current() ; it.Next())
						{
						writer << *it.Current();
						}
					}
				}
			
			writer.WriteInt32L(iDisplayCalibrationMessage);
			
			writer.WriteInt32L(iUseLocation);
			}

			
			writer.CommitL(); // all buffered data is written out
			}
		CleanupStack::PopAndDestroy(&writer); // release resources 
		return err;
	}


void CSingaporeBusDocument::EnableLogs()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	_LIT(kLogDirectoryPath, "C:\\Logs\\SingaporeBus\\");
	iFsData.MkDirAll(kLogDirectoryPath);	

	{
	TFileName path;
	iFsLogs.SessionPath(path);
	iFsLogs.MkDirAll(path);	
	}
	
	iFileLogger.CloseLog();
	iFileLogger.CreateLog(_L("SingaporeBus"),_L("TraceFile.txt"),EFileLoggingModeOverwrite);
	}

void CSingaporeBusDocument::HandleForegroundEventL(TBool aForeground)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(aForeground)
		iTimeInBackground.HomeTime();
	else
		iTimeInBackground = Time::MaxTTime();
	}

void CSingaporeBusDocument::DisableLogs()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	_LIT(kLogDirectoryPath, "C:\\Logs\\SingaporeBus\\");
	
	iFileLogger.CloseLog();
	
	TInt err;

	CFileMan* fileMan = CFileMan::NewL(iFsData);
	CleanupStack::PushL(fileMan); 
	TFileName strName(kLogDirectoryPath);
	for( ; (err = fileMan->RmDir(kLogDirectoryPath)) == KErrInUse ; User::After(1000000) );
	
	{
	TFileName path;
	iFsLogs.SessionPath(path);
	for( ; (err = fileMan->RmDir(path)) == KErrInUse ; User::After(1000000) );
	}

	CleanupStack::PopAndDestroy(fileMan);
	
	iFileLogger.CreateLog(_L("SingaporeBus"),_L("TraceFile.txt"),EFileLoggingModeOverwrite);
	}

void CSingaporeBusDocument::ConnectL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iConnectionManager->IsConnecting()) return;
	iConnectionManager->ConnectL(this);
	}

void CSingaporeBusDocument::InitConnectionManagerL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iConnectionManager;
	iConnectionManager = CIapConnectionManager::NewL();
	
	//_LIT8(KUserAgent, "Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaN95/35.0.002; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413");
	//_LIT8(KUAProf, "http://nds1.nds.nokia.com/uaprof/NN95-1r100.xml");
	_LIT8(KUserAgent, "SBSTransitIris/60 CFNetwork/485.12.7 Darwin/10.4.0");
	_LIT8(KAccept, "*/*");
	RHTTPHeaders httpHeader = iConnectionManager->iSession.RequestSessionHeadersL();
	SetHeaderL(iConnectionManager->iSession, httpHeader, HTTP::EUserAgent, KUserAgent);
	SetHeaderL(iConnectionManager->iSession, httpHeader, HTTP::EAccept, KAccept);
	//_LIT8(KClose, "close");
	//SetHeaderL(iConnectionManager->iSession, httpHeader, HTTP::EConnection, KClose);
	const TStringTable& stringTable = RHTTPSession::GetTable();
	
	if(1 == 0) // disable auto re-direction
	{
	RHTTPFilterCollection filtColl = iConnectionManager->iSession.FilterCollection();
	RStringF filterName = iConnectionManager->iSession.StringPool().StringF(HTTP::ERedirect,RHTTPSession::GetTable());
	filtColl.RemoveFilter( filterName );
	}
	
	
	{
	RStringPool strP = iConnectionManager->iSession.StringPool();
	RHTTPConnectionInfo connInfo = iConnectionManager->iSession.ConnectionInfo();

	connInfo.SetPropertyL(
			strP.StringF(HTTP::EMaxNumTransactionsToPipeline, stringTable ),
			THTTPHdrVal( 6 ) );
	connInfo.SetPropertyL(
			strP.StringF(HTTP::EMaxNumTransportHandlers, stringTable ),
			THTTPHdrVal( 5 ) );
	connInfo.SetPropertyL(
			strP.StringF(HTTP::EMaxNumTransPerTranspHndlr, stringTable ),
			THTTPHdrVal( 6 ) );	
	}
	iConnectionManager->SetIapPriorityList(&iIapPriorityList);
	
	}

RFile sRemoteLogFile;

void CSingaporeBusDocument::InitWorkerThread()
	{
	RFbsSession::Connect();
	}
void CSingaporeBusDocument::UninitWorkerThread()
	{
	RFbsSession::Disconnect();
	}

/**
 * @brief Completes the second phase of Symbian object construction. 
 * Put initialization code that could leave here.  
 */ 
void CSingaporeBusDocument::ConstructL()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	iWorkerThread = new (ELeave) CWorkerThread;
	
	
	iWorkerThread->Start( scalp::MakeFunctionL(scalp::Bind(&CSingaporeBusDocument::InitWorkerThread, this)) );


	{
#ifdef __WINSCW__
	TFileName path = _L("C:");
#else
	TFileName path = Application()->AppFullName().Left(2);
#endif
	TFileName privatePath;
	User::LeaveIfError(iFsData.Connect());
	iFsData.PrivatePath(privatePath);
	path.Append(privatePath);
	iFsData.MkDirAll(path);	
	User::LeaveIfError(iFsData.SetSessionPath(path));
	}
	
	_LIT(kLogDirectoryPath, "C:\\Logs\\SingaporeBus\\");
	{
#ifdef __WINSCW__
	TFileName path = _L("C:");
#else
	TFileName path = Application()->AppFullName().Left(2);
#endif
	TFileName privatePath;
	path.Append(_L("\\Data\\SingaporeBus\\"));
	User::LeaveIfError(iFsLogs.Connect());
	if(BaflUtils::FolderExists(iFsData, kLogDirectoryPath))
		iFsLogs.MkDirAll(path);	
	User::LeaveIfError(iFsLogs.SetSessionPath(path));	
	}

	{
#ifdef __WINSCW__
	TFileName path = _L("Z:");
#else
	TFileName path = Application()->AppFullName().Left(2);
#endif	
	path.Append(_L("\\resource\\apps\\"));
	User::LeaveIfError(iFsResource.Connect());
	User::LeaveIfError(iFsResource.SetSessionPath(path));
	User::LeaveIfError(iFsResource.ShareProtected()); // needed such that servers (FBSERV) may use the session
	}
			

	{
		_LIT(kLogFileName, "C:\\Logs\\SingaporeBus\\TraceFile.txt");
		if(BaflUtils::FileExists(iFsLogs, kLogFileName))
			{
			// the log file exists because of a crash, copy it to our private directory
			TBuf<128> targetFileName;
			for(TInt i = 1 ; targetFileName.Length() == 0 || BaflUtils::FileExists(iFsLogs, targetFileName) ; i++)
				targetFileName.Format(_L("TraceFile%d.txt"), i);
			BaflUtils::CopyFile(iFsLogs, kLogFileName, targetFileName);
			}
	}
	
	iFileLogger.Connect();
	iFileLogger.CreateLog(_L("SingaporeBus"),_L("TraceFile.txt"),EFileLoggingModeOverwrite);
	TFunTrace::setFileLogger(&iFileLogger);
	
	
	{
	iIsConnectionActiveHelper = CActiveHelper<RConnection*>::NewL();	
	InitConnectionManagerL();
	ConnectL();
	}

	// we always initially have one folder favourite
	iFavoritesTitles.AppendL( _L("Favorites").AllocL() );
	iFavorites.AppendL( new RHashSet< TBuf8<15> >(&TBuf8Hash, &TBuf8Ident) );
	TUint settingsVersion;
	if(LoadSettingsL(settingsVersion) == KErrNotFound || settingsVersion < 3)
		{
		SaveSettingsL(); // enables to freeze iLastAutoCheckForUpdate 
		}
		
	
	iBusStopsListShowMode = KShowAll;
	iCurrentFavorite = -1; // ShowAll
	
	User::LeaveIfError(iGpsGraceTimer.CreateLocal());
	iGpsGraceTimerHelper = CActiveHelper<RTimer*>::NewL();
	iInitLocationServicesAsyncCallback = new (ELeave) CAsyncCallBack( TCallBack(&MemFunDelegate<CSingaporeBusDocument, &CSingaporeBusDocument::InitLocationServices>, this), CActive::EPriorityIdle);
	iInitLocationServicesAsyncCallback->CallBack();
#ifndef __SERIES60_3X__
    User::LeaveIfError( iCompassTimer.CreateLocal() );
    User::LeaveIfError( iCalibrationMessageTimer.CreateLocal() );
    User::LeaveIfError( iCalibrationMessageAnimationTimer.CreateLocal() );
    
	iCompassTimerTarget = new scalp::CActiveTarget(
			scalp::MakeFunctionL(scalp::Bind(&RTimer::Cancel, &iCompassTimer))
			);
	iCompassTimerTarget->AppendRunL( scalp::MakeFunctionL(scalp::Bind(&CSingaporeBusDocument::StopCompassTrackingL, this)) );
	iCalibrationMessageTimerTarget = new scalp::CActiveTarget(
			scalp::MakeFunctionL(scalp::Bind(&RTimer::Cancel, &iCalibrationMessageTimer))
			);
	iCalibrationMessageTimerTarget->AppendRunL( scalp::MakeFunctionL(scalp::Bind(&CSingaporeBusDocument::DisplayCalibrationMessageL, this)) );
	
	iCalibrationMessageAnimationTimerTarget = new scalp::CActiveTarget(
			scalp::MakeFunctionL(scalp::Bind(&RTimer::Cancel, &iCalibrationMessageAnimationTimer))
			);
	iCalibrationMessageAnimationTimerTarget->AppendRunL( scalp::MakeFunctionL(scalp::Bind(&CSingaporeBusDocument::CalibrationAnimationMessageCallbackL, this)) );
#endif
	
	

	
	{
		iStationsFileLoader = CAsyncFileLoader::NewL();
		iServicesFileLoader = CAsyncFileLoader::NewL();
		iServicesPathsFileLoader = CAsyncFileLoader::NewL();
		iServicesPathsIndexFileLoader = CAsyncFileLoader::NewL();
		iStationsFileLoader->LoadFileL(iFsData, _L("stations.txt"), this);
	}

	
	{
	
		if(iInstallationFile.Length())
			{
			if(iFsData.Delete(iInstallationFile) == KErrNone)
				{
				iInstallationFile.Zero();
				SaveSettingsL();
				}
			}
		iApplicationUpdater = CApplicationUpdater::NewL();
		TFileName downloadPath;
#ifdef __WINSCW__
		downloadPath.Append(_L("C:"));
#else
		downloadPath.Append(Application()->AppFullName().Left(2));
#endif
		downloadPath.Append(_L("\\SingaporeBus.sis"));
		iApplicationUpdater->SetApplicationInformationL(
				_L("SingaporeBus"), _L8( APPLICATION_VERSION ),
#ifdef OVI
				_L8("https://projects.developer.nokia.com/SingaporeBus/files/manifestovi.txt"),
#elif defined(SELFSIGNED)
				_L8("https://projects.developer.nokia.com/SingaporeBus/files/manifest.txt"),
#else
				_L8("https://projects.developer.nokia.com/SingaporeBus/files/manifestcs.txt"),
#endif
				downloadPath,
				APPLICATION_UPDATER_RESOURCES
				);
	
	}
	iApplicationUpdater->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	
	iSmrtSession = CSmrtSession::NewL();
	iSmrtSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iIrisSession = CIrisSession::NewL();
	iIrisSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iTflSession = CTflSession::NewL();
	iTflSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iHow2GoQuery = CHow2GoQuery::NewL();
	iHow2GoQuery->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iTflJourneyPlannerQuery = CTFLJourneyPlannerQuery::NewL();
	iTflJourneyPlannerQuery->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iAdSession  = CAdSession::NewL(); 
	iAdSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	
	iMapTileServer = new (ELeave) CMapTileServer;
	{
#ifdef __WINSCW__
	TFileName path = _L("C:");
#else
	TFileName path = Application()->AppFullName().Left(2);
#endif
	TFileName privatePath;
	iFsData.PrivatePath(privatePath);
	path.Append(privatePath);
	path.Append(_L("TileCache\\"));
	iMapTileServer->ConstructL(iWorkerThread.Get(), path, iCachedTilesCount);
	}
	iMapTileServer->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	
	iServicesStationMap = new(ELeave) RHashMap< TBuf8<15>, const TStation*>(&TBuf8Hash, &TBuf8Ident);


	
	if(1 == 0)
	{
	iLogFile.Replace(CCoeEnv::Static()->FsSession(), _L("C:\\Data\\log.txt"), EFileWrite);
	}
	
	}


struct CUseLocationDialog : public CAknQueryDialog
	{
	CUseLocationDialog() { }
	virtual void SetSizeAndPosition(const TSize& aSize)
		{
		CAknDialog::SetSizeAndPosition( aSize );  
		CAknQueryControl* queryControl = (CAknQueryControl*)Control(EGeneralQuery);
		CAknMessageQueryControl* messageQueryControl = (CAknMessageQueryControl*)Control(EAknMessageQueryContentId);
		queryControl->ComponentControl(0)->SetExtent(
				Position(),
				TSize(aSize.iWidth, 30)
				);
		messageQueryControl->ComponentControl(0)->SetExtent(
				queryControl->Position() + TPoint(0, queryControl->Rect().Height()),
				TSize(aSize.iWidth, aSize.iHeight - queryControl->Rect().Height())
				);
		}
	};


struct CCalibrationDialog : public CAknListQueryDialog
	{
	LManagedPtr< scalp::CFunction< void(CCalibrationDialog*, TInt, CArrayFixFlat<TInt>*) > > iCallback;
	LManagedPtr< CArrayFixFlat<TInt> > iIndexArray;
	CCalibrationDialog( scalp::CFunction< void(CCalibrationDialog*, TInt, CArrayFixFlat<TInt>*) >* aCallback ) : iCallback(aCallback), iIndexArray ( new ( ELeave ) CArrayFixFlat<TInt>( 1 ) ), CAknListQueryDialog(iIndexArray.Get()) { }
	virtual TBool OkToExitL( TInt aButtonId )
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		TBool ret = CAknListQueryDialog::OkToExitL(aButtonId);
		(*iCallback)(this, aButtonId, iIndexArray.Get());
    	return ret;
		}
	void TryExitL(TInt aButtonId)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CAknListQueryDialog::TryExitL(aButtonId);
		}
	
	void Draw(const TRect& aRect) const
	{
	CAknListQueryDialog::Draw(aRect);
	
	/*CGraphicsContext& gc=SystemGc();
	gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor(KRgbRed);
	gc.SetBrushStyle(CGraphicsContext::ENullBrush);

	gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor(KRgbRed);
	gc.DrawRect(ListControl()->Rect());

	gc.SetPenStyle(CGraphicsContext::ESolidPen); gc.SetPenColor(KRgbBlue);
	gc.DrawRect(ListControl()->Listbox()->Rect());*/
	}
	
	
	virtual void SetSizeAndPosition(const TSize& aSize)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		CEikImage* image = (CEikImage*)Control(1);
		TSize imageSize = image->Bitmap()->SizeInPixels();

		CEikFormattedCellListBox* listBox = ListControl()->Listbox();
		CAknListQueryDialog::SetSizeAndPosition( aSize );
		listBox->SetExtent(
				listBox->Position() + TPoint(0, imageSize.iHeight),
				TSize(listBox->Size().iWidth, listBox->View()->ItemSize().iHeight)
				);
		/*
		 * Works
		CAknListQueryDialog::SetSizeAndPosition( aSize );
		CEikFormattedCellListBox* listBox = ListControl()->Listbox();
		SetExtent(
			Position() - TPoint(0, Min(imageSize.iHeight, Position().iY)),
			//listBox->Size() + TSize(0, imageSize.iHeight) + TSize(0, controlPaneRect.Height())
			Size() + TSize(0, imageSize.iHeight)
			);
		listBox->SetExtent(
				TPoint(0, imageSize.iHeight),
				TSize(Size().iWidth, listBox->Size().iHeight)
				);
		
		CFormattedCellListBoxData *boxData =
	        ((CEikFormattedCellListBox*)ListBox())->ItemDrawer()->FormattedCellData();
	    TRect outerRect = Rect(); outerRect.Shrink(2,0);
	    TRect innerRect = outerRect; innerRect.Shrink(5,5);
	    boxData->SetSkinPopupFramePosition(outerRect, innerRect);*/
	    
	    /*delete iBgContext;
	    TRect rect = Rect();
		iBgContext = CAknsFrameBackgroundControlContext::NewL(
				KAknsIIDQsnFrPopup, rect, rect, ETrue );
		iBgContext->SetParentPos( PositionRelativeToScreen() );
		
		ListControl()->SetMopParent(this);*/

		{
		TInt flags(ListControl()->Listbox()->ItemDrawer()->Flags());
		flags |= CListItemDrawer::EDisableHighlight;
		ListControl()->Listbox()->ItemDrawer()->SetFlags(flags);
		ListControl()->Listbox()->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOff);
		}
		}
	
	};


struct TAnimationFrame
	{
	TInt64 iFrameDuration;
	TInt iFrameId;
	};
TAnimationFrame kCalibrationAnimation[] =
{
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe1},
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe2},
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe3},
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe2},
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe1},
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe2},
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe3},
		{1*1000000, EMbmSingaporebus_aifCompasscalibrationframe2},
		{30*1000000, EMbmSingaporebus_aifCompasscalibrationframe1}
};
const TInt64 kCalibrationAnimationLoop = 38*1000000; // the sum of all kCalibrationAnimation durations

void CSingaporeBusDocument::CalibrationAnimationMessageCallbackL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(!iCalibrationDialog || iCalibrationMessageAnimationTimerTarget->iStatus != KErrNone) return; // dialog must have been dismissed
	
	// find the currentFrame
	TTime time;
	time.HomeTime();
	TInt64 frameTime = (time.MicroSecondsFrom(iCalibrationAnimationMessageStart).Int64() % kCalibrationAnimationLoop);
	TInt frameIt;
	TInt64 frameTimeIt = frameTime;
	for(frameIt = 0 ;
		frameIt < sizeof(kCalibrationAnimation)/sizeof(kCalibrationAnimation[0]) &&
		frameTimeIt >  kCalibrationAnimation[frameIt].iFrameDuration
		; frameTimeIt -= kCalibrationAnimation[frameIt].iFrameDuration, frameIt++);
		
	if(frameIt < sizeof(kCalibrationAnimation)/sizeof(kCalibrationAnimation[0]))
	{
	_LIT( kSingaporeBus_aifFile, "\\resource\\apps\\SingaporeBus_aif.mif" );
	CFbsBitmap* bitmap = AknIconUtils::CreateIconL(kSingaporeBus_aifFile, kCalibrationAnimation[frameIt].iFrameId);
	CWsScreenDevice* screenDevice = CEikonEnv::Static()->ScreenDevice();
	AknIconUtils::SetSize(bitmap, 
			TSize(280, 220)
			//TSize(screenDevice->SizeInPixels().iWidth*3/4, screenDevice->SizeInPixels().iHeight*3/4)
			);
	CEikImage* imageControl = (CEikImage*)iCalibrationDialog->Control(1);
	delete imageControl->Bitmap();
	imageControl->SetBitmap(bitmap);
	imageControl->DrawDeferred();

	iCalibrationMessageAnimationTimerTarget->Cancel();
	iCalibrationMessageAnimationTimer.After(iCalibrationMessageAnimationTimerTarget->iStatus, kCalibrationAnimation[frameIt].iFrameDuration - frameTimeIt);
	iCalibrationMessageAnimationTimerTarget->SetActive();
	}
	
	}


TInt CSingaporeBusDocument::InitLocationServices()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	RefreshPosition();
	return KErrNone;
	}



void CSingaporeBusDocument::CalibrationDialogCallback(CCalibrationDialog* aDialog, TInt aButtonId, CArrayFixFlat<TInt>* aIndexArray)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(aButtonId == EAknSoftkeyClose)
		{
		if(aDialog->ListBox()->SelectionIndexes()->Count() > 0) // "do not display again" is ticked
			{
			iDisplayCalibrationMessage = EFalse;
			SaveSettingsL();
			}
		}
	iCalibrationDialog = NULL; // the dialog will be deleted by RunLD
	}

void CSingaporeBusDocument::DisplayCalibrationMessageL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iCalibrationMessageTimerTarget->iStatus == KErrNone)
		{
		if(!iCalibrationDialog)
			{
			iCalibrationDialog = new (ELeave) CCalibrationDialog(scalp::MakeFunctionL( scalp::Bind(&CSingaporeBusDocument::CalibrationDialogCallback, this, scalp::Free1, scalp::Free2, scalp::Free3) ));
			iCalibrationDialog->PrepareLC(R_CALIBRATION_DIALOG);
			{
			_LIT( kSingaporeBus_aifFile, "\\resource\\apps\\SingaporeBus_aif.mif" );
			CFbsBitmap* bitmap = AknIconUtils::CreateIconL(kSingaporeBus_aifFile, kCalibrationAnimation[0].iFrameId);
			CWsScreenDevice* screenDevice = CEikonEnv::Static()->ScreenDevice();
			AknIconUtils::SetSize(bitmap, 
					TSize(280, 220)
					//TSize(screenDevice->SizeInPixels().iWidth*3/4, screenDevice->SizeInPixels().iHeight*3/4)
					);
			CEikImage* imageControl = (CEikImage*)iCalibrationDialog->Control(1);
			imageControl->SetSize(bitmap->SizeInPixels());
			delete imageControl->Bitmap();
			imageControl->SetBitmap(bitmap);
			}
			iCalibrationDialog->RunLD();
			iCalibrationAnimationMessageStart.HomeTime();
			iCalibrationMessageAnimationTimerTarget->Cancel();
			iCalibrationMessageAnimationTimer.After(iCalibrationMessageAnimationTimerTarget->iStatus, kCalibrationAnimation[0].iFrameDuration);
			iCalibrationMessageAnimationTimerTarget->SetActive();
			}
		}
	}


#ifndef __SERIES60_3X__

void CSingaporeBusDocument::RefreshCompass()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iMagneticNorthSensor.Get())
		{
		TTime time;
		time.HomeTime();
		if(time.MicroSecondsFrom(iTimeStartRefreshCompass) <= 60*1000000)
			{
			//iMagneticNorthSensor->StartDataListeningL( this, 1, 1, 0 );                 
			}
		else
			{
			iMagneticNorthSensor = NULL;
			iMagnetometerSensor = NULL;
			iMagnetometerCalibrationLevel = 0; // Not calibrated
		    iMagneticNorthDataError = KErrNotFound;
			}
		}
	}


void CSingaporeBusDocument::StopCompassTrackingL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iCompassTimerTarget->iStatus != KErrCancel)
		{
		iMagneticNorthSensor = NULL;
		iMagnetometerSensor = NULL;
		iMagnetometerCalibrationLevel = 0; // Not calibrated
		iMagneticNorthDataError = KErrNotFound;
		TriggerNotifyAzimuthChanged();
		iCalibrationMessageTimerTarget->Cancel();
		if(iCalibrationDialog)
			iCalibrationDialog->TryExitL(EAknSoftkeyClose);
		}
	}

void CSingaporeBusDocument::PropertyChanged( CSensrvChannel& aChannel, 
		const TSensrvProperty& aChangedProperty )
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	TSensrvChannelInfo info = aChannel.GetChannelInfo();
	if (info.iChannelType == KSensrvChannelTypeIdMagnetometerXYZAxisData)
		{
		if(aChangedProperty.GetPropertyId()==KSensrvPropCalibrationLevel)
			{
			aChangedProperty.GetValue(iMagnetometerCalibrationLevel);
			
			if(iMagnetometerCalibrationLevel > 0)
				{
				iCalibrationMessageTimerTarget->Cancel();
				if(iCalibrationDialog)
					iCalibrationDialog->TryExitL(EAknSoftkeyClose);
				}
			}
		}
	}
void CSingaporeBusDocument::PropertyError( CSensrvChannel& aChannel, TSensrvErrorSeverity aError )
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	PrintNoteL(_L("PropertyError: %d"), aError);
	
	}
void CSingaporeBusDocument::SetPropertySuccessIndicationChanged(TSetPropertySuccessIndicator aIndication )
	{
	
	}
void CSingaporeBusDocument::GetPropertyListenerInterfaceL( TUid aInterfaceUid, TAny*& aInterface )
	{
	
	}

void CSingaporeBusDocument::DataReceived(CSensrvChannel& aChannel, TInt aCount, TInt aDataLost)
	{
	//TFunTrace funTrace(__PRETTY_FUNCTION__); // too frequent
    if ( aChannel.GetChannelInfo().iChannelType == KSensrvChannelTypeIdMagneticNorthData)
        {
        TSensrvMagneticNorthData prevMagneticNorthData = iMagneticNorthData;
        TPckg<TSensrvMagneticNorthData> magneticNorthDataPackage( iMagneticNorthData );
        aChannel.GetData( magneticNorthDataPackage );
        iMagneticNorthDataError = KErrNone;
        

        if( iMagnetometerCalibrationLevel != iDataReceived_PrevMagnetometerCalibrationLevel || prevMagneticNorthData.iAngleFromMagneticNorth != iMagneticNorthData.iAngleFromMagneticNorth)
        	{
			TriggerNotifyAzimuthChanged();
        	}
        iDataReceived_PrevMagnetometerCalibrationLevel = iMagnetometerCalibrationLevel;
        
        }
	
	}
void CSingaporeBusDocument::DataError(CSensrvChannel& aChannel, TSensrvErrorSeverity aError)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	PrintNoteL(_L("DataError: %d"), aError);
	}
void CSingaporeBusDocument::GetDataListenerInterfaceL(TUid aInterfaceUid, TAny*& aInterface)
	{
	
	}

#endif

void CSingaporeBusDocument::PowerDownL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iSmrtSession->CloseConnectionL();
	iIrisSession->CloseConnectionL();
	iTflSession->CloseConnectionL();
	iHow2GoQuery->CloseConnectionL();
	iAdSession->CloseConnectionL();
	iMapTileServer->CloseConnectionL();
	iTflJourneyPlannerQuery->CloseConnectionL();
	iApplicationUpdater->CloseConnectionL();
	if(iGooglePositionRequest)
		iGooglePositionRequest->CloseConnectionL();
	iIsConnectionActiveHelper->Cancel();
	InitConnectionManagerL();
	iSmrtSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iIrisSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iTflSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iHow2GoQuery->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iTflJourneyPlannerQuery->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iAdSession->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iApplicationUpdater->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	iMapTileServer->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	if(iGooglePositionRequest)
		iGooglePositionRequest->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
	}



void CSingaporeBusDocument::MActiveHelperCallbackRunL(CActiveHelper<RConnection*>* aActiveHelper, RConnection* aConnection)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(aActiveHelper->iStatus == KErrNone)
		{
		/*
		 * iConnectionActive = EFalse always with Symbian^3...
		 * 
		if(iConnectionActive())
			{
			iConnectionManager->iConnection.IsConnectionActiveRequest(30, iConnectionActive, iIsConnectionActiveHelper->iStatus);
			iIsConnectionActiveHelper->SetActive(this, &iConnectionManager->iConnection);		
			}
		else
			 */
			{
//#ifndef __WINS__ // emulator detects inactivity much sooner than 3*60 seconds...
			PowerDownL();
//#endif
			}
		}
	}
TInt CSingaporeBusDocument::MActiveHelperCallbackRunError(CActiveHelper<RConnection*>* aActiveHelper, RConnection* aConnection, TInt aError)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	}
void CSingaporeBusDocument::MActiveHelperCallbackDoCancel(CActiveHelper<RConnection*>* aActiveHelper, RConnection* aConnection)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(aActiveHelper == iIsConnectionActiveHelper)
		aConnection->IsConnectionActiveCancel();
	}



TPtrC CSingaporeBusDocument::PositionDescription()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	switch(iPositioningStatus)
		{
		case PS_NOT_AVAILABLE: return _L("Position not avail.");
		case PS_ERROR:
			{
			iPositionDescriptionBuf.Format(_L("Pos. error %d"), iPositionError);
			return iPositionDescriptionBuf;
			}
		case PS_PENDING: return _L("Req. position...");
		case PS_FOUND:
			{
			iPositionDescriptionBuf.Format(_L("%S"), &iPositionModuleName);
			return iPositionDescriptionBuf;
			}
		}
	}



void CSingaporeBusDocument::RefreshPosition()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);


	// checks whether the position comes from GPS partially (ETechnologyAssisted) or totally (ETechnologyTerminal)
	// http://developer.symbian.org/main/documentation/reference/s3/pdk/GUID-F6B5F777-D12F-5913-AECE-047DF8C72F1F.html
	iPositionTracking = EFalse;
	if(iPositioningStatus == PS_FOUND && (iPositioningTechnology & (TPositionModuleInfo::ETechnologyTerminal | TPositionModuleInfo::ETechnologyAssisted)))
		{
		if(iPrevGPSPositions.Count() > 4)
			iPrevGPSPositions.Remove(0);
		iPrevGPSPositions.AppendL(iPosition);
		
		}
	
	if(iAskUseLocation)
		{
		CAknMessageQueryDialog* dlg = new (ELeave) CAknMessageQueryDialog();
		dlg->PrepareLC(R_USE_LOCATION_DIALOG);
		dlg->SetMessageTextL(_L("Authorize SingaporeBus to access your location?\n\nYour location is only used to locate nearby bus stations and is never sent to our servers or to any 3rd party.\nYou may change this option at any time in Settings."));
		iUseLocation = (dlg->RunLD() == EAknSoftkeyYes);
		SaveSettingsL();
		iAskUseLocation = EFalse;
		}
	
	if(iUseLocation)
		{
	
		
		{
		if(!iGooglePositionRequest)
			{
			RProcess proc;
			if(proc.HasCapability(ECapabilityReadDeviceData, NULL))
				{
				iGooglePositionRequest = CGooglePositionRequest::NewL();
				iGooglePositionRequest->SetConnectionInfoL(iConnectionManager->iConnection, iConnectionManager->iSockServ);
				}
			}
	
		if(!iPositionRequest)
			{
			RProcess proc;
			if(proc.HasCapability(ECapabilityLocation, NULL))
				{
				iPositionRequest = CPositionRequest::NewL();
				iPositionRequest->OpenL();
				TInt availableModules = 0;
				{
					RPositionServer& positionServer = iPositionRequest->PositionServer();
					TUint moduleCount;
					User::LeaveIfError(positionServer.GetNumModules(moduleCount));
					for(TUint i = 0 ; !iGpsAvailable && i < moduleCount ; i++)
						{
						TPositionModuleInfo modInfo;
						User::LeaveIfError( positionServer.GetModuleInfoByIndex( i, modInfo ) );
						if(modInfo.IsAvailable())
							{
							++availableModules;
							if (modInfo.TechnologyType() == TPositionModuleInfo::ETechnologyTerminal)
								iGpsAvailable = ETrue;
							}
						}
				}
				if(availableModules)
					{
					iPositionRequest->SetRequestorL(_L("First GPS Application"));
					iPositionRequest->Positioner().SetUpdateOptions(
						 TPositionUpdateOptions( TTimeIntervalMicroSeconds(0),
												 TTimeIntervalMicroSeconds(60*1000000), /* timeout */
												 TTimeIntervalMicroSeconds(0), /* max age */
												 EFalse));
					}
				else
					{
					delete iPositionRequest;
					iPositionRequest = NULL;
					}
				}
			}
					
	
		if(!iNetworkPositionRequest)
			{
			RProcess proc;
			if(proc.HasCapability(ECapabilityLocation, NULL))
				{
			
				iNetworkPositionRequest = CPositionRequest::NewL();
				TBool openModule = iNetworkPositionRequest->OpenL( TPositionModuleInfo::ETechnologyNetwork );
				if(openModule)
					{
					iNetworkPositionRequest->SetRequestorL(_L("First GPS Application"));
					iNetworkPositionRequest->Positioner().SetUpdateOptions(
						 TPositionUpdateOptions( 0,
												 TTimeIntervalMicroSeconds(0), /* timeout */
												 TTimeIntervalMicroSeconds(0), /* max age */
												 EFalse));
					}
				else
					{
					delete iNetworkPositionRequest;
					iNetworkPositionRequest = NULL;
					}
				}
			}
		}
		
		if(iPositionRequest)
			{
			iPositionRequest->Cancel();
			iPositionRequest->SubmitL(this);
			iPendingPositionRequests++;
			}
			
	#ifndef __SERIES60_3X__
			if(!iMagnetometerSensor.Get())
			{
				LCleanedupHandle<RSensrvChannelInfoList> channelInfoList;
				LCleanedupPtr<CSensrvChannelFinder> channelFinder ( CSensrvChannelFinder::NewL() );
				TSensrvChannelInfo channelInfo;
				channelInfo.iChannelType = KSensrvChannelTypeIdMagnetometerXYZAxisData;
				channelFinder->FindChannelsL( channelInfoList.Get(), channelInfo );
				if( channelInfoList->Count() > 0 )
				{
					iMagnetometerSensor = CSensrvChannel::NewL( (*channelInfoList)[ 0 ] );
					iMagnetometerSensor->OpenChannelL();
					{
					TSensrvProperty property;
					iMagnetometerSensor->GetPropertyL(KSensrvPropAutoCalibrationActive, KSensrvItemIndexNone, property);
					property.SetValue(1); // set auto-calibration on. Note, do SetValue(0) to disable auto-calibration
					iMagnetometerSensor->SetProperty(property);
					}
					{
					TSensrvProperty property;
					iMagnetometerSensor->GetPropertyL(KSensrvPropCalibrationLevel, KSensrvItemIndexNone, property);
					property.GetValue(iMagnetometerCalibrationLevel);
					}
					iMagnetometerSensor->SetPropertyListenerL(this);
					iMagnetometerSensor->StartDataListeningL(this, 1, 1, 0);
					
				}	
			}
			if(iMagnetometerSensor && iMagnetometerCalibrationLevel == 0)
			{
			iCalibrationMessageTimerTarget->Cancel();
			iCalibrationMessageTimer.After(iCalibrationMessageTimerTarget->iStatus, 10*1000000);
			iCalibrationMessageTimerTarget->SetActive();
			}
			
			if(!iMagneticNorthSensor.Get())
				{
				//Construct a channel finder.
				LCleanedupPtr<CSensrvChannelFinder> channelFinder ( CSensrvChannelFinder::NewL() );
				{
					LCleanedupHandle<RSensrvChannelInfoList> channelInfoList;
					TSensrvChannelInfo channelInfo;
					channelInfo.iChannelType = KSensrvChannelTypeIdMagneticNorthData;
					channelFinder->FindChannelsL( channelInfoList.Get(), channelInfo );
					if( channelInfoList->Count() > 0 )
					{
						iMagneticNorthSensor = CSensrvChannel::NewL( (*channelInfoList)[ 0 ] );
						iMagneticNorthSensor->OpenChannelL();
						iMagneticNorthDataError = KErrNotFound;
						iTimeStartRefreshCompass.HomeTime();
						iMagneticNorthSensor->StartDataListeningL( this, 1, 1, 0 );                 
					}	
				}
		
				}
			
		if(iMagnetometerSensor.Get() || iMagneticNorthSensor.Get())
			{
			iCompassTimerTarget->Cancel();
			iCompassTimer.Inactivity(iCompassTimerTarget->iStatus, 60*10);
			iCompassTimerTarget->SetActive();
			}
	#endif
			
			
			
			
		iGooglePositionRequestWaitingConnection = EFalse;
		
		iGpsGraceTimerHelper->Cancel();
		iGpsGraceTimer.After(iGpsGraceTimerHelper->iStatus, iGpsAvailable ? iGpsGraceTime*1000000 : 0);
		iGpsGraceTimerHelper->SetActive(this, &iGpsGraceTimer);
		
		/*
		if(iGooglePositionRequest)
			{
			iGooglePositionRequest->Cancel();
			if(iConnected)
				iGooglePositionRequest->SubmitL(iConnectionManager->iSession, this);
			}
		if(iNetworkPositionRequest)
			{
			iNetworkPositionRequest->Cancel();
			if(iNetworkPositionRequestOpenModuleSuccess)
				iNetworkPositionRequest->SubmitL(this);
			}*/
		}

	if(iUseLocation && ( iPositionRequest || iGooglePositionRequest || iNetworkPositionRequest) )
		iPositioningStatus  = PS_PENDING;
	else
		iPositioningStatus = PS_NOT_AVAILABLE;
	TriggerNotifyPositionChange();
	}

CSingaporeBusDocument::~CSingaporeBusDocument()
	{
	
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	
	
	iSmrtSession = NULL; // need to be released before connection is closed
	iIrisSession = NULL;
	iTflSession = NULL;
	iJourneyPlannerOutput = NULL;
	iHow2GoQuery = NULL;
	iAdSession = NULL;
	iMapTileServer = NULL;
	
	iStationUnderlying = NULL;
	iStationOrderIterator = NULL;

	delete iApplicationUpdater;
	
	delete iGpsGraceTimerHelper;
	iGpsGraceTimer.Close();

#ifndef __SERIES60_3X__
	delete iCompassTimerTarget;
    iCompassTimer.Close();
	delete iCalibrationMessageTimerTarget;
	iCalibrationMessageTimer.Close();
	delete iCalibrationMessageAnimationTimerTarget;
	iCalibrationMessageAnimationTimer.Close();
#endif

	
	delete iStationsFileLoader;
	delete iServicesFileLoader;
	delete iServicesPathsFileLoader;
	delete iServicesPathsIndexFileLoader;
	
	for(TUint i = 0 ; i < iStationsLoaded.Count() ; ++i)
		delete iStationsLoaded[i];
	iStationsLoaded.Close();
	iFavoriteStations.Close();
	
	for(TInt i = 0 ; i < iFavorites.Count() ; ++i)
		{
		iFavorites[i]->Close();
		delete iFavorites[i];
		delete iFavoritesTitles[i];
		}
	iFavorites.Close();
	iFavoritesTitles.Close();

	iStations.Close();
	iServices.Close();
	iServicesPathsIndex.Close();
	iStationServiceKeys.Close();
	iServiceStations.Close();
	iServicePaths.Close();
	iServicePathsCoordinates.Close();
	
	iStationsBuf.Close();
	iServicesBuf.Close();
	iServicesPathsIndexBuf.Close();
	iServicesPathsBuf.Close();
	iServicesSortedByServiceKey.Close();
	iServicesPathsIndexSortedByKey.Close();
	iStationsSortedByStationNumber.Close();
	
	if(iServicesStationMap) iServicesStationMap->Close();
	delete iServicesStationMap;
	iServicesStationMap = NULL;

	
	delete iIsConnectionActiveHelper;
	delete iGooglePositionRequest;
	delete iPositionRequest;
	delete iNetworkPositionRequest;
	delete iHow2GoQuery.Unmanage();
	delete iConnectionManager;
	iIapPriorityList.Close();
	for(TInt i = 0 ; i < iDisplayServiceKeys.Count() ; delete iDisplayServiceKeys[i++]);
	iDisplayServiceKeys.Close();
	iPrevGPSPositions.Close();
	
	

	if(iFileLogger.Handle())
		{
		iFileLogger.Write(_L("Logger closes"));
		iFileLogger.CloseLog();
		iFileLogger.Close();
		}
	TFunTrace::setFileLogger(NULL);
	
	{
		_LIT(kLogFileName, "C:\\Logs\\SingaporeBus\\TraceFile.txt");
		if(iFsLogs.Handle() && BaflUtils::FileExists(iFsLogs, kLogFileName))
			{
			TBuf<128> targetFileName;
			for(TInt i = 1 ; targetFileName.Length() == 0 || BaflUtils::FileExists(iFsLogs, targetFileName) ; i++)
				targetFileName.Format(_L("TraceFile%d-OK.txt"), i);
			for( ; BaflUtils::CopyFile(iFsLogs, kLogFileName, targetFileName) == KErrInUse ; User::After(1000000) );
			for( ; iFsLogs.Delete(kLogFileName) == KErrInUse ; User::After(1000000) );
			}
	}
	
	iLogFile.Close();
	iFsResource.Close();
	iFsData.Close();
	iFsLogs.Close();
	
	iWorkerThread->Execute( scalp::MakeFunctionL(scalp::Bind(&CSingaporeBusDocument::UninitWorkerThread, this)) );
	iWorkerThread->Stop();
		
	}


/**
 * Symbian OS two-phase constructor.
 *
 * Creates an instance of CSingaporeBusDocument, constructs it, and
 * returns it.
 *
 * @param aApp the application instance
 * @return the new CSingaporeBusDocument
 */
CSingaporeBusDocument* CSingaporeBusDocument::NewL( CEikApplication& aApp )
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	CSingaporeBusDocument* self = new ( ELeave ) CSingaporeBusDocument( aApp );
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop( self );
	return self;
	}

/**
 * @brief Creates the application UI object for this document.
 * @return the new instance
 */	
CEikAppUi* CSingaporeBusDocument::CreateAppUiL()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	return new ( ELeave ) CSingaporeBusAppUi;
	}
				

void CSingaporeBusDocument::MIapConnectionManagerCallbackRunL(TInt aStage, TInt aError)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	switch(aStage)
		{
		 case KConnectionUninitialised:
			break;
		case -1:
			if(aError == KErrNone)
				{
				TriggerNotifyConnected();
				iIsConnectionActiveHelper->Cancel();
				iConnectionActive() = ETrue;
				iConnectionManager->iConnection.IsConnectionActiveRequest(60*3, iConnectionActive, iIsConnectionActiveHelper->iStatus);
				iIsConnectionActiveHelper->SetActive(this, &iConnectionManager->iConnection);

				if(iGooglePositionRequest && iGooglePositionRequestWaitingConnection && iPositioningStatus != PS_FOUND)
					{
					iGooglePositionRequest->SubmitL(this);
					iPendingPositionRequests++;
					iPositioningStatus = PS_PENDING;
					TriggerNotifyPositionChange();
					}
				
				TTime now;
				now.HomeTime();
				if(iApplicationUpdaterWaitingConnection || (iCountAutoCheckForUpdateInSession == 0 && iAutoCheckForUpdatePeriod >= 0 && !iApplicationUpdater->UpdatePending() && now.DaysFrom(iLastAutoCheckForUpdate).Int() >= iAutoCheckForUpdatePeriod))
					{
					iApplicationUpdater->StartUpdateSequenceL(ETrue, this);
					iApplicationUpdaterWaitingConnection = EFalse;
					}
				}
			break;
		}	
	}

void CSingaporeBusDocument::TriggerNotifyAzimuthChanged()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	CSingaporeBusStopsView* singaporeBusStopsView = static_cast<CSingaporeBusStopsView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusStopsViewId)));
	if(singaporeBusStopsView)
		singaporeBusStopsView->NotifyAzimuthChange();

	CSingaporeBusServicesView* singaporeBusServicesView = static_cast<CSingaporeBusServicesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesViewId)));
	if(singaporeBusServicesView)
		singaporeBusServicesView->NotifyAzimuthChange();

	CSingaporeBusRouteView* singaporeBusRouteView = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId)));
	if(singaporeBusRouteView)
		singaporeBusRouteView->NotifyAzimuthChange();

	CSingaporeBusRouteView* singaporeBusRouteView2 = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId2)));
	if(singaporeBusRouteView2)
		singaporeBusRouteView2->NotifyAzimuthChange();

	CSingaporeBusFavoritesView* singaporeBusFavoriteView = static_cast<CSingaporeBusFavoritesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusFavoritesViewId)));
	if(singaporeBusFavoriteView)
		singaporeBusFavoriteView->NotifyAzimuthChange();

	CSingaporeBusFavoritesView* singaporeBusFavoritesView2 = static_cast<CSingaporeBusFavoritesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusFavoritesViewId2)));
	if(singaporeBusFavoritesView2)
		singaporeBusFavoritesView2->NotifyAzimuthChange();

	CSingaporeBusServiceRouteView* singaporeBusServiceRouteView = static_cast<CSingaporeBusServiceRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServiceRouteViewId)));
	if(singaporeBusServiceRouteView)
		singaporeBusServiceRouteView->NotifyAzimuthChange();

	CSingaporeBusServicesArrivalTimeView* singaporeBusServicesArrivalTimeView = static_cast<CSingaporeBusServicesArrivalTimeView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesArrivalTimeViewId)));
	if(singaporeBusServicesArrivalTimeView)
		singaporeBusServicesArrivalTimeView->NotifyAzimuthChange();
	
	CPublicTransportMapContainerView* publicTransportMapContainerView = static_cast<CPublicTransportMapContainerView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(EPublicTransportMapContainerViewId)));
	if(publicTransportMapContainerView)
		publicTransportMapContainerView->NotifyAzimuthChange();
	}


void CSingaporeBusDocument::TriggerNotifyConnected()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(!CEikonEnv::Static()->AppUi()) return;
	
	CPublicTransportMapContainerView* publicTransportMapContainerView = static_cast<CPublicTransportMapContainerView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(EPublicTransportMapContainerViewId)));
	if(publicTransportMapContainerView)
		publicTransportMapContainerView->NotifyConnected();
	
	
	/*CSingaporeBusStopsView* singaporeBusStopsView = static_cast<CSingaporeBusStopsView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusStopsViewId)));
	if(singaporeBusStopsView)
		singaporeBusStopsView->NotifyConnected();

	CSingaporeBusServicesView* singaporeBusServicesView = static_cast<CSingaporeBusServicesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesViewId)));
	if(singaporeBusServicesView)
		singaporeBusServicesView->NotifyConnected();*/

	CSingaporeBusRouteView* singaporeBusRouteView = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId)));
	if(singaporeBusRouteView)
		singaporeBusRouteView->NotifyConnected();

	CSingaporeBusRouteView* singaporeBusRouteView2 = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId2)));
	if(singaporeBusRouteView2)
		singaporeBusRouteView2->NotifyConnected();

	CSingaporeBusServiceRouteView* singaporeBusServiceRouteView = static_cast<CSingaporeBusServiceRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServiceRouteViewId)));
	if(singaporeBusServiceRouteView)
		singaporeBusServiceRouteView->NotifyConnected();

	CSingaporeBusServicesArrivalTimeView* singaporeBusServicesArrivalTimeView = static_cast<CSingaporeBusServicesArrivalTimeView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesArrivalTimeViewId)));
	if(singaporeBusServicesArrivalTimeView)
		singaporeBusServicesArrivalTimeView->NotifyConnected();
	
	CSingaporeBusFavoritesView* singaporeBusFavoritesView = static_cast<CSingaporeBusFavoritesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusFavoritesViewId)));
	if(singaporeBusFavoritesView)
		singaporeBusFavoritesView->NotifyConnected();
	
	CSingaporeBusFavoritesView* singaporeBusFavoritesView2 = static_cast<CSingaporeBusFavoritesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusFavoritesViewId2)));
	if(singaporeBusFavoritesView2)
		singaporeBusFavoritesView2->NotifyConnected();
	
	CSingaporeBusServicesView* singaporeBusServicesView = static_cast<CSingaporeBusServicesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesViewId)));
	if(singaporeBusServicesView)
		singaporeBusServicesView->NotifyConnected();
	
	{
	if(iJourneyPlannerError != KErrNone)
		SubmitJourneyPlannerQueryL();
	}
	
	
	}

template<class T>
inline T Square(const T& aT)
	{
	return aT*aT;
	}



TReal32 CSingaporeBusDocument::StationOrderItem(const TStation* aStation)
	{
	TReal32 distance = 0;
	if(iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
		distance = Square(iPosition.Longitude() - aStation->iCoord.Longitude()) +
		Square(iPosition.Latitude() - aStation->iCoord.Latitude())
		;
	return distance;
	}


void CSingaporeBusDocument::TriggerNotifyPositionChange()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(!CEikonEnv::Static()->AppUi()) return;
	
	
	if(iPositioningStatus == CSingaporeBusDocument::PS_FOUND && iStations.Count() && iServices.Count())
	{
	iStationUnderlying = new (ELeave) CArrayPtrIterator<const TStation*>(&iStations[0], iStations.Count());
	iStationOrderIterator = new (ELeave) COrderingIterator<const TStation*, TReal32>(
			iStationUnderlying.Get(),
			scalp::MakeFunctionL( scalp::Bind(&CSingaporeBusDocument::StationOrderItem, this, scalp::Free1) )
			);
	TInt servicesCount = 0;
	if(iServicesStationMap) iServicesStationMap->Close();
	delete iServicesStationMap;
	iServicesStationMap = new(ELeave) RHashMap< TBuf8<15>, const TStation*>(&TBuf8Hash, &TBuf8Ident);
	while(iStationOrderIterator->HasNext() && servicesCount < iServices.Count())
		{
		const TStation* station;
		if(iStationOrderIterator->Next(station))
			{
			for(TInt j = station->iServicesBeg ; j < station->iServicesEnd ; ++j)
				{
				const TDesC8& serviceKey = iStationServiceKeys[j];
				TBuf8<15> upperServiceKey = serviceKey;
				upperServiceKey.UpperCase();
				if(iServicesStationMap->Find(upperServiceKey) == NULL)
					{
					iServicesStationMap->Insert(upperServiceKey, station);
					++servicesCount;
					}
				}
			}
		}
	}
	
	CPublicTransportMapContainerView* publicTransportMapContainerView = static_cast<CPublicTransportMapContainerView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(EPublicTransportMapContainerViewId)));
	if(publicTransportMapContainerView)
		publicTransportMapContainerView->NotifyPositionChange();

	CSingaporeBusStopsView* singaporeBusStopsView = static_cast<CSingaporeBusStopsView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusStopsViewId)));
	if(singaporeBusStopsView)
		singaporeBusStopsView->NotifyPositionChange();

	CSingaporeBusServicesView* singaporeBusServicesView = static_cast<CSingaporeBusServicesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesViewId)));
	if(singaporeBusServicesView)
		singaporeBusServicesView->NotifyPositionChange();

	CSingaporeBusRouteView* singaporeBusRouteView = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId)));
	if(singaporeBusRouteView)
		singaporeBusRouteView->NotifyPositionChange();

	CSingaporeBusRouteView* singaporeBusRouteView2 = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId2)));
	if(singaporeBusRouteView2)
		singaporeBusRouteView2->NotifyPositionChange();

	CSingaporeBusFavoritesView* singaporeBusFavoriteView = static_cast<CSingaporeBusFavoritesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusFavoritesViewId)));
	if(singaporeBusFavoriteView)
		singaporeBusFavoriteView->NotifyPositionChange();

	CSingaporeBusFavoritesView* singaporeBusFavoritesView2 = static_cast<CSingaporeBusFavoritesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusFavoritesViewId2)));
	if(singaporeBusFavoritesView2)
		singaporeBusFavoritesView2->NotifyPositionChange();

	CSingaporeBusServiceRouteView* singaporeBusServiceRouteView = static_cast<CSingaporeBusServiceRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServiceRouteViewId)));
	if(singaporeBusServiceRouteView)
		singaporeBusServiceRouteView->NotifyPositionChange();

	CSingaporeBusServicesArrivalTimeView* singaporeBusServicesArrivalTimeView = static_cast<CSingaporeBusServicesArrivalTimeView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesArrivalTimeViewId)));
	if(singaporeBusServicesArrivalTimeView)
		singaporeBusServicesArrivalTimeView->NotifyPositionChange();
	
	CSingaporeBusAppUi* singaporeBusAppUi = (CSingaporeBusAppUi*)iAppUi;
	if(singaporeBusAppUi)
		singaporeBusAppUi->NotifyPositionChange();
	
	}

void CSingaporeBusDocument::TriggerNotifyFileLoaded(const CAsyncFileLoader* aFileLoader)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(!CEikonEnv::Static()->AppUi()) return;
	
	CPublicTransportMapContainerView* publicTransportMapContainerView = static_cast<CPublicTransportMapContainerView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(EPublicTransportMapContainerViewId)));
	if(publicTransportMapContainerView)
		publicTransportMapContainerView->NotifyFileLoaded(aFileLoader);
	
	CSingaporeBusServicesView* singaporeBusServicesView = static_cast<CSingaporeBusServicesView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesViewId)));
	if(singaporeBusServicesView)
		singaporeBusServicesView->NotifyFileLoaded(aFileLoader);
	
	CSingaporeBusServicesArrivalTimeView* singaporeBusServicesArrivalTimeView = static_cast<CSingaporeBusServicesArrivalTimeView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServicesArrivalTimeViewId)));
	if(singaporeBusServicesArrivalTimeView)
		singaporeBusServicesArrivalTimeView->NotifyFileLoaded(aFileLoader);
	
	CSingaporeBusStopsView* singaporeBusStopsView = static_cast<CSingaporeBusStopsView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusStopsViewId)));
	if(singaporeBusStopsView)
		singaporeBusStopsView->NotifyFileLoaded(aFileLoader);
	
	CSingaporeBusServiceRouteView* singaporeBusServiceRouteView = static_cast<CSingaporeBusServiceRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusServiceRouteViewId)));
	if(singaporeBusServiceRouteView)
		singaporeBusServiceRouteView->NotifyFileLoaded(aFileLoader);
	}


void CSingaporeBusDocument::MGooglePositionRequestCallbackRunL(TInt aStatus, TInt aLastError, const TCoordinate& aPosition, TReal32 aAccuracy)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	iPendingPositionRequests--;
	
	if(aStatus != THTTPEvent::EFailed)
		{
		TPosition pos;
		TPositionModuleInfo::TTechnologyType positioningTechnology = TPositionModuleInfo::ETechnologyUnknown;
		
		TReal32 distanceFromLastPosition;
		TTimeIntervalMicroSeconds microSecondsFromLastPosition;
		if(iPositioningStatus == PS_FOUND)
			{
			TTime currentTime;
			currentTime.HomeTime();
			microSecondsFromLastPosition = currentTime.MicroSecondsFrom(iPositionTime);
			iPosition.Distance(aPosition, distanceFromLastPosition);
			}
		
		
		if(		iPositioningStatus != PS_FOUND
				|| aAccuracy < iPositionAccuracy
				|| distanceFromLastPosition > iPositionAccuracy + aAccuracy )
			{
			iPositioningStatus = PS_FOUND;
			iPositioningTechnology = positioningTechnology;
			iPositionModuleName.Copy(_L("Google"));
			iPosition = aPosition;
			iPositionTime.HomeTime();
			iPositionAccuracy = aAccuracy;
			TriggerNotifyPositionChange();
			}
		}
	else
		{
		if(!iPendingPositionRequests && iPositioningStatus != PS_FOUND)
			{
			iPositioningStatus = PS_ERROR;
			iPositionError = aLastError;
			TriggerNotifyPositionChange();
			}
		if(aLastError == KErrNotReady || aLastError == KErrConnectionTerminated) // not connected or connection lost
			{
			ConnectL();
			iGooglePositionRequestWaitingConnection = ETrue;
			}
		}
	}


void CSingaporeBusDocument::MPositionRequestCallbackRunL(CPositionRequest* aPositionRequest, const TRequestStatus& aStatus, const TPositionInfo& aPositionInfo)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	iPendingPositionRequests--;
	
	if(aStatus == KErrNone)
		{
		TPosition pos;
		aPositionInfo.GetPosition(pos);
		TReal32 posAccuracy = pos.HorizontalAccuracy();
		
		if(aPositionRequest == iPositionRequest)
			iGpsGraceTimerHelper->Cancel();
		
		TBool positionIsConsistent = ETrue;
		TReal32 distanceFromLastPosition;
		TTimeIntervalMicroSeconds microSecondsFromLastPosition;
		if(iPositioningStatus == PS_FOUND)
			{
			TTime currentTime;
			currentTime.HomeTime();
			microSecondsFromLastPosition = currentTime.MicroSecondsFrom(iPositionTime);
			iPosition.Distance(pos, distanceFromLastPosition);
			
			if(	iPositionModuleName == _L("Google")
				&& distanceFromLastPosition - posAccuracy - iPositionAccuracy > microSecondsFromLastPosition.Int64()/1000000 * 25*1000/3600 )
				positionIsConsistent = EFalse;
			}
		

		TPositionModuleInfo posModuleInfo;
		aPositionRequest->PositionServer().GetModuleInfoById(aPositionInfo.ModuleId(), posModuleInfo);
		TPositionModuleInfo::TTechnologyType positioningTechnology = posModuleInfo.TechnologyType();
		if(		(iPositionTracking && positionIsConsistent)
				|| iPositioningStatus != PS_FOUND
				|| (posAccuracy < iPositionAccuracy && positionIsConsistent) )
			{
			iPosition = pos;
			iPositioningStatus = PS_FOUND;
			iPositionTime.HomeTime();
			iPositioningTechnology = positioningTechnology;
			posModuleInfo.GetModuleName(iPositionModuleName);
			iPositionAccuracy = pos.HorizontalAccuracy();
			TriggerNotifyPositionChange();
			}
		
		TTime currentTime;
		currentTime.HomeTime();
		TTimeIntervalSeconds intervalSeconds;
		currentTime.SecondsFrom(iTimeInBackground, intervalSeconds);
		if(aPositionRequest == iPositionRequest && intervalSeconds.Int() < 120)
			{
			//iPositionTracking = ETrue;
			//aPositionRequest->SubmitL(this);
			}
		
 		}
	else
		{
		if(!iPendingPositionRequests && iPositioningStatus != PS_FOUND)
			{
			iPositioningStatus = PS_ERROR;
			iPositionError = aStatus.Int();
			TriggerNotifyPositionChange();
			}
		}
	}


static TInt TLinearOrder_IndexITem(const TIndexItem* const& left, const TIndexItem* const& right)
	{
	TInt ret = left->iKey.Compare(right->iKey);
	if(ret > 0) return 1;
	if(ret < 0) return -1;
	return 0;
	}


TBool CSingaporeBusDocument::LoadServicePathL(const TDesC8& aServiceKey)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);

	TIndexItem target = { aServiceKey };
	TInt ret = iServicesPathsIndexSortedByKey.SpecificFindInOrder(&target, TLinearOrder<const TIndexItem*>(&TLinearOrder_IndexITem), EArrayFindMode_Any);
	if(ret == KErrNotFound) return EFalse;
	iServicesPathsFileLoader->Cancel();
	iServicesPathsFileLoader->LoadFileL(iFsData, _L("servicespaths.txt"), this, iServicesPathsIndexSortedByKey[ret]->iOffset, iServicesPathsIndexSortedByKey[ret]->iSize);
    return ETrue;
	}

TBool CSingaporeBusDocument::LoadCurrentDisplayServiceL()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);

	TIndexItem target = { *iDisplayServiceKeys[iCurrentDisplayServiceKey] };
	TInt ret = iServicesPathsIndexSortedByKey.SpecificFindInOrder(&target, TLinearOrder<const TIndexItem*>(&TLinearOrder_IndexITem), EArrayFindMode_Any);
	if(ret == KErrNotFound) return EFalse;
	iServicesPathsFileLoader->Cancel();
	iServicesPathsFileLoader->LoadFileL(iFsData, _L("servicespaths.txt"), this, iServicesPathsIndexSortedByKey[ret]->iOffset, iServicesPathsIndexSortedByKey[ret]->iSize);
    return ETrue;
	}

// ================
// ================
// ================


void CSingaporeBusDocument::MAsyncFileLoaderCallbackRunL(CAsyncFileLoader* aSource, TInt aStatus, RBuf8& aBuf)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(aSource == iStationsFileLoader)
		{
		iStationsBuf.Swap(aBuf);
		iStations.ReserveL(4500);
		iStationServiceKeys.Reserve(20000);		
		ParseStationsL(iStationsBuf, iStations, iStationServiceKeys);
		iStationsSortedByStationNumber.Reserve( iServices.Count() );

		for(TInt i = 0 ; i < iStations.Count() ; ++i)
			iStationsSortedByStationNumber.AppendL( &iStations[i] );
		iStationsSortedByStationNumber.Sort(TLinearOrder<const TStation*>(&TLinearOrder_Station));
		
		iStations.Compress();
		iStationsSortedByStationNumber.Compress();
		iStationServiceKeys.Compress();
		}
	else if(aSource == iServicesFileLoader)
		{
		iServicesBuf.Swap(aBuf);
		iServices.ReserveL(1000);
		iServiceStations.Reserve(21000);
		ParseServicesL(iServicesBuf, iServices, iServiceStations);
		iServicesSortedByServiceKey.Reserve( iServices.Count() );

		for(TInt i = 0 ; i < iServices.Count() ; ++i)
			iServicesSortedByServiceKey.AppendL( &iServices[i] );
		iServicesSortedByServiceKey.Sort(TLinearOrder<const TService*>(&TLinearOrder_Service));
		
		iServices.Compress();
		iServiceStations.Compress();
		iServicesSortedByServiceKey.Compress();
		}
	else if(aSource == iServicesPathsIndexFileLoader)
		{
		iServicesPathsIndexBuf.Swap(aBuf);
		iServicesPathsIndex.ReserveL(1000);
		ParseIndexL(iServicesPathsIndexBuf, iServicesPathsIndex);
		iServicesPathsIndexSortedByKey.ReserveL( iServicesPathsIndex.Count() );
		
		for(TInt i = 0 ; i < iServicesPathsIndex.Count() ; ++i)
			iServicesPathsIndexSortedByKey.AppendL( &iServicesPathsIndex[i] );
		iServicesPathsIndexSortedByKey.Sort(TLinearOrder<const TIndexItem*>(&TLinearOrder_IndexITem));
		
		if(iDisplayServiceKeys.Count())
			LoadCurrentDisplayServiceL();
		
		iServicesPathsIndex.Compress();
		}
	else if(aSource == iServicesPathsFileLoader)
		{
		iServicesPathsBuf.Swap(aBuf);
		iServicePaths.Reset();
		iServicePathsCoordinates.Reset();
		ParseServicePathsL(iServicesPathsBuf, iServicePaths, iServicePathsCoordinates);
		}

	TriggerNotifyFileLoaded(aSource);
	if(aSource == iStationsFileLoader)
		{
		iServicesFileLoader->LoadFileL(iFsData, _L("services.txt"), this);
		}
	else if(aSource == iServicesFileLoader)
		{
		iServicesPathsIndexFileLoader->LoadFileL(iFsData, _L("servicespathsindex.txt"), this);
		}	
	}



void CSingaporeBusDocument::MApplicationUpdaterCallbackRunL(const TApplicationUpdaterEvent& aEvent)
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
switch(aEvent)
	{
	case EAUE_EXIT:
		iInstallationFile.Copy( iApplicationUpdater->DownloadPath() );
		SaveSettingsL(); // iLastAutoCheckForUpdate
		((CSingaporeBusAppUi*)(CEikonEnv::Static()->AppUi()))->HandleCommandL( EEikCmdExit );
	break;
	case EAUE_MANIFEST_DOWNLOADED:
		iLastAutoCheckForUpdate.HomeTime();
		iCountAutoCheckForUpdateInSession++;
		SaveSettingsL(); // iLastAutoCheckForUpdate
		break;
	case EAUE_CONNECTION_ERROR:
		ConnectL();
		iApplicationUpdaterWaitingConnection = ETrue;
		break;
	}

}


void CSingaporeBusDocument::MActiveHelperCallbackRunL(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	
	if(aTimer == &iGpsGraceTimer)
		{
		if(iGooglePositionRequest)
			{
				iGooglePositionRequest->SubmitL(this);
				iPendingPositionRequests++;
			}
		if(iNetworkPositionRequest)
			{
			iNetworkPositionRequest->Cancel();
			iNetworkPositionRequest->SubmitL(this);
			iPendingPositionRequests++;
			}
		}
	}
TInt CSingaporeBusDocument::MActiveHelperCallbackRunError(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer, TInt aError)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	}
void CSingaporeBusDocument::MActiveHelperCallbackDoCancel(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	aTimer->Cancel();
	}

TInt CSingaporeBusDocument::TLinearOrder_Service(const TService* const& left, const TService* const& right)
	{
	TInt ret = left->iServiceKey.Compare(right->iServiceKey);
	if(ret > 0) return 1;
	if(ret < 0) return -1;
	return 0;
	}

TInt CSingaporeBusDocument::TLinearOrder_Station(const TStation* const& left, const TStation* const& right)
	{
	TInt ret = left->iStationNumber.Compare(right->iStationNumber);
	if(ret > 0) return 1;
	if(ret < 0) return -1;
	return 0;
	}


void CSingaporeBusDocument::ToggleFavoriteL(const TDesC8& aStrFavorite, TInt aFavoriteGroup)
	{
	if((iFavorites[aFavoriteGroup])->Find(aStrFavorite))
		iFavorites[aFavoriteGroup]->Remove(aStrFavorite);
	else
		iFavorites[aFavoriteGroup]->InsertL(aStrFavorite);
	SaveSettingsL();
	}

void CSingaporeBusDocument::StoreFavoriteL(TDes8& aBuf, const TService* aService) const
	{
	aBuf.Format(_L8("#%S"), &aService->iServiceKey);
	}
void CSingaporeBusDocument::StoreFavoriteL(TDes8& aBuf, const TStation* aStation) const
	{
	aBuf.Format(_L8("%S"), &aStation->iStationNumber);
	}
void CSingaporeBusDocument::StoreFavoriteL(TDes8& aBuf, const TStation* aStation, const TService* aService) const
	{
	aBuf.Format(_L8("&%S %S"), &aStation->iStationNumber, &aService->iServiceKey);
	}

TInt CSingaporeBusDocument::FindFavorite(const TDes8& aBuf) const
{
TInt i;
TBool isFavorite = EFalse;
for(i = 0 ; i < iFavorites.Count() && !isFavorite ; ++i)
	{
	const TBuf8<15>* find = iFavorites[i]->Find(aBuf);
	isFavorite = ( find != NULL);
	}
if(isFavorite) return i - 1;
return KErrNotFound;
}

TInt CSingaporeBusDocument::FindFavorite(const TService* aService) const
{
	TBuf8<128> favoriteStr;
	StoreFavoriteL(favoriteStr, aService);
	return FindFavorite(favoriteStr);
}
TInt CSingaporeBusDocument::FindFavorite(const TStation* aStation) const
{
	TBuf8<128> favoriteStr;
	StoreFavoriteL(favoriteStr, aStation);
	return FindFavorite(favoriteStr);
}
TInt CSingaporeBusDocument::FindFavorite(const TStation* aStation, const TService* aService) const
{
	TBuf8<128> favoriteStr;
	StoreFavoriteL(favoriteStr, aStation, aService);
	return FindFavorite(favoriteStr);
}



void CSingaporeBusDocument::SetOriginL(const TStation* aStation)
	{
	iOriginStation = aStation;
	RefreshRouteL();
	}
void CSingaporeBusDocument::SetDestinationL(const TStation* aStation)
	{
	iDestinationStation = aStation;
	RefreshRouteL();
	}


struct CRouteOptionDialog : public CAknDialog
	{
	TInt i;
	CRouteOptionDialog() { }
    virtual TBool OkToExitL(TInt aButtonId)
    	{
    	CAknListQueryControl* travelOriginControl = 
			(CAknListQueryControl*)(static_cast<CAknQueryControl*>(Control(ERouteTravelOrigin)))->ControlByLayoutOrNull(EMultiDataFirstEdwin);
    	TInt travelOrigin = travelOriginControl->Listbox()->CurrentItemIndex();
    	CAknListQueryControl* travelOptionControl = 
			(CAknListQueryControl*)(static_cast<CAknQueryControl*>(Control(ERouteTravelOption)))->ControlByLayoutOrNull(EMultiDataFirstEdwin);
    	TInt travelOption = travelOptionControl->Listbox()->CurrentItemIndex();
    	CEikTimeEditor* travelTimeControl = 
			(CEikTimeEditor*)(static_cast<CAknQueryControl*>(Control(ERouteTravelOption)))->ControlByLayoutOrNull(EMultiDataFirstEdwin);
    	TTime travelTime = travelTimeControl->Time();
    	return CEikDialog::OkToExitL(aButtonId);
    	}
    
	};


void CSingaporeBusDocument::How2GoQueryAnswerL(CHow2GoQuery*, TInt aLastError, TInt aStatusCode, CJourneyPlannerOutput* aOutput)
	{
	iJourneyPlannerError = aLastError;
	iJourneyPlannerStatusCode = aStatusCode;
	iJourneyPlannerOutput = aOutput;
	CSingaporeBusRouteView* singaporeBusRouteView = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId)));
	if(singaporeBusRouteView)
		singaporeBusRouteView->NotifyJourneyPlannerQueryAnswerL();
	
	CSingaporeBusAppUi* appUi = (CSingaporeBusAppUi*)iAvkonViewAppUi;
	appUi->NotifyJourneyPlannerQueryAnswerL();
	
	if(iJourneyPlannerError == KErrNotReady || iJourneyPlannerError == KErrConnectionTerminated || iJourneyPlannerError == DndTimedOut) // not connected or connection lost
		ConnectL();
	}
void CSingaporeBusDocument::TflJourneyPlannerQueryAnswerL(CTFLJourneyPlannerQuery*, TInt aLastError, TInt aStatusCode, CJourneyPlannerOutput* aOutput)
	{
	iJourneyPlannerError = aLastError;
	iJourneyPlannerStatusCode = aStatusCode;
	iJourneyPlannerOutput = aOutput;
	CSingaporeBusRouteView* singaporeBusRouteView = static_cast<CSingaporeBusRouteView*>(static_cast<CAknViewAppUi*>(CEikonEnv::Static()->AppUi())->View(TUid::Uid(ESingaporeBusRouteViewId)));
	if(singaporeBusRouteView)
		singaporeBusRouteView->NotifyJourneyPlannerQueryAnswerL();
	
	CSingaporeBusAppUi* appUi = (CSingaporeBusAppUi*)iAvkonViewAppUi;
	appUi->NotifyJourneyPlannerQueryAnswerL();
	
	if(iJourneyPlannerError == KErrNotReady || iJourneyPlannerError == KErrConnectionTerminated || iJourneyPlannerError == DndTimedOut) // not connected or connection lost
		ConnectL();
	}


void CSingaporeBusDocument::SubmitJourneyPlannerQueryL()
	{
	iJourneyPlannerOutput = NULL;
	iJourneyPlannerError = KErrNone;
	if(iOriginStation->iStationType == TStation::ELDNormal)
		iTflJourneyPlannerQuery->SubmitL(
				iOriginStation->iAddress2,
				iDestinationStation->iAddress2,
				iTravelOption,
				scalp::MakeFunctionL( scalp::Bind(&CSingaporeBusDocument::TflJourneyPlannerQueryAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) )
		);
	else
		iHow2GoQuery->SubmitL(
			iOriginStation->iCoord,
			iDestinationStation->iCoord,
			iTravelOption,
			scalp::MakeFunctionL( scalp::Bind(&CSingaporeBusDocument::How2GoQueryAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) )
		);
	}


void CSingaporeBusDocument::RefreshRouteL()
	{
	if(iOriginStation && iDestinationStation)
		{
		if(iOriginStation->iStationType != TStation::ELDNormal)
			{
			TInt retTravelOptionQuery = ((CSingaporeBusAppUi*)CEikonEnv::Static()->AppUi())->RunSelectTravelOptionQueryL();
			switch(retTravelOptionQuery)
				{
				case -1: return;
				case 0:
					iTravelOption = 2; // bus + MRT
					break;
				case 1:
					iTravelOption = 0; // bus only
					break;
				default:
					iTravelOption = retTravelOptionQuery;
					break;
				}
			}
			SubmitJourneyPlannerQueryL();
			iAvkonViewAppUi->ActivateLocalViewL(TUid::Uid( ESingaporeBusRouteViewId ));
		}
	}


void CSingaporeBusDocument::CreateFavoritePaneL(const TDesC& aPaneName)
	{
	iFavorites.AppendL( new RHashSet< TBuf8<15> >(&TBuf8Hash, &TBuf8Ident) );
	iFavoritesTitles.AppendL( aPaneName.AllocL() );
	SaveSettingsL(); // enables to freeze iLastAutoCheckForUpdate 
	}


void CSingaporeBusDocument::DeleteFavoritePaneL(TInt aPaneId)
	{
	iFavorites[aPaneId]->Close();
	delete iFavorites[aPaneId];
	iFavorites.Remove(aPaneId);
	delete iFavoritesTitles[aPaneId];
	iFavoritesTitles.Remove(aPaneId);
	SaveSettingsL(); // enables to freeze iLastAutoCheckForUpdate 
	}

void CSingaporeBusDocument::RenameFavoritePaneL(TInt aPaneId, const TDesC& aPaneName)
	{
	delete iFavoritesTitles[aPaneId];
	iFavoritesTitles[aPaneId] = aPaneName.AllocL();
	SaveSettingsL(); // enables to freeze iLastAutoCheckForUpdate 
	}


CAknToolbar* sArrivalTimeToolbar = NULL;
